package com.kvn.test.stepdefs;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.testng.Assert;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Splitter;
import com.kvn.test.core.TestContext;
import com.kvn.test.dubbo.DubboCommand;
import com.kvn.test.dubbo.DubboCommandExecutor;
import com.kvn.test.util.SpELUtil;

import cucumber.api.java.en.Given;

/**
 * Dubbo调用指令
 * 
 * @author wzy on 2017/8/8.
 */
public class DubboStepdefs {
	private Logger logger = LoggerFactory.getLogger(DubboStepdefs.class);

	@Given("^CALL_DUBBO->(.*)$")
	public void callDubbo(String dubboUrl, String methodParams) throws Throwable {
		logger.info("【指令】CALL_DUBBO->" + dubboUrl + "，参数：" + methodParams);
		DubboCommand command = parseDubboCommand(dubboUrl, methodParams);
		DubboCommandExecutor executor = new DubboCommandExecutor();
		executor.dubboExecute(command);
	}

	private DubboCommand parseDubboCommand(String dubboUrl, String methodParams) {
		String methodUrl = dubboUrl.split("\\?")[0];
		String[] interMethod = methodUrl.split("#");
		Assert.assertEquals(interMethod.length, 2, "dubbo方法配置错误。示例：com.kvn.XxService#method1");

		String interfaceName = interMethod[0].trim();
		String methodName = interMethod[1].trim();

		DubboCommand command = new DubboCommand();
		BeanWrapper bw = new BeanWrapperImpl(command);
		bw.setPropertyValue("interfaceName", interfaceName);
		bw.setPropertyValue("methodName", methodName);

		// dubbo url 参数解析
		Pattern pattern = Pattern.compile("[?&][^?&]+=[^?&]+");
		Matcher matcher = pattern.matcher(dubboUrl);
		while (matcher.find()) {
			String item = matcher.group();
			String[] kv = item.substring(1).split("=");
			bw.setPropertyValue(kv[0].trim().toLowerCase(), kv[1].trim()); // key全部为小写
		}

		/************************ dubbo 方法参数解析 **********************/
		if (StringUtils.isBlank(methodParams)) {
			return command;
		}

		String[] paramArr = methodParams.replaceAll("\r\n", "\n").split("\n");
		for (String param : paramArr) {
			processByLine(param, command);
		}

		return command;
	}

	/**
	 * 按行来处理参数
	 * @param param
	 * @param command
	 */
	private void processByLine(String param, DubboCommand command) {
		String[] param_value = param.split("=", 2);
		Assert.assertEquals(param_value.length, 2, "调用参数配置异常：" + param);
		
		String type = param_value[0].trim();
		String value = param_value[1].trim();
		if("${null}".equals(value.toLowerCase())){
			command.appendArg(type, null);
			return;
		}
		
		Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
		Matcher matcher = pattern.matcher(value);
		while(matcher.find()){
			String expression = matcher.group(1);
			Object parsed = SpELUtil.getValue(expression);
			value = matcher.replaceFirst(JSON.toJSONString(parsed));
			matcher = pattern.matcher(value);
		}
		
		if (typeInJava(type)) { // java 里面的类型
			command.appendArg(type, value);
		} else { // 复杂参数用 Map
			// @see https://dubbo.gitbooks.io/dubbo-user-book/content/demos/generic-reference.html
			JSONObject jsonObj = JSON.parseObject(value);
			command.appendArg(type, jsonObj); // JSONObject 实现了Map接口
		}
	}

	/**
	 * java 里面的数据类型
	 * @param type
	 * @return
	 */
	private boolean typeInJava(String type) {
		if(type.startsWith("java.")){
			return true;
		}
		if("byte,short,int,long,float,double,boolean,char".contains(type)){
			return true;
		}
		return false;
	}

	public static void main(String[] args) {
		String s = "a\nb\r\nc\n\rd\r";
		String s1 = "a:b:c:d";
		String[] arr1 = s1.split(":", 2);
		String[] arr = s.replaceAll("\r", "\n").split("\n");
		System.out.println(s);
	}
}
